package com.liruo.treasureattic.common.util.crypto;

import cn.hutool.core.date.DateUtil;
import cn.hutool.jwt.JWT;
import cn.hutool.jwt.JWTPayload;
import cn.hutool.jwt.JWTUtil;
import cn.hutool.jwt.signers.JWTSigner;
import cn.hutool.jwt.signers.JWTSignerUtil;
import com.liruo.treasureattic.common.httpmsg.exception.ValidatorException;
import com.liruo.treasureattic.common.httpmsg.result.Errno;
import com.liruo.treasureattic.common.util.DefaultTimeUtils;

import java.util.Date;
import java.util.Map;

/**
 * @Author:liruo
 * @Date:2022-11-10-10:37:46
 * @Desc
 */
public class JwtUtil {
    public final static long DEFAULT_EXPIRES_ADD_DAY = 15;
    public static String createToken(String secretKey, Map<String,Object> payloads){
        Date issuedAt = new Date();
        Date expiresAt = DefaultTimeUtils.toDate(DefaultTimeUtils.toLocalDateTime(issuedAt).plusDays(DEFAULT_EXPIRES_ADD_DAY));
        return createToken(secretKey, payloads, issuedAt, expiresAt);
    }
    public static String createToken(String secretKey, Map<String,Object> payloads,long expiresAddDay){
        Date issuedAt = new Date();
        Date expiresAt = DefaultTimeUtils.toDate(DefaultTimeUtils.toLocalDateTime(issuedAt).plusDays(expiresAddDay));
        return createToken(secretKey, payloads, issuedAt, expiresAt);
    }

    private static String createToken(String secretKey, Map<String, Object> payloads, Date issuedAt, Date expiresAt) {
        JWTSigner signer = JWTSignerUtil.hs256(secretKey.getBytes());
        return JWT.create()
                .setSigner(signer)
                .setIssuedAt(issuedAt)
                .setExpiresAt(expiresAt)
                .addPayloads(payloads)
                .sign();
    }

    /**
     * 自己加Payloads，最后必须调用sign()方法
     */
    public static JWT createJWT(String secretKey,long expiresAddDay){
        JWTSigner signer = JWTSignerUtil.hs256(secretKey.getBytes());
        Date issuedAt = new Date();
        Date expiresAt = DefaultTimeUtils.toDate(DateUtil.toLocalDateTime(issuedAt).plusDays(expiresAddDay));
        return JWT.create()
                .setSigner(signer)
                .setIssuedAt(issuedAt)
                .setExpiresAt(expiresAt);
    }


    /**
     * 需要捕捉ValidateException
     */
    public static void verifyAlgorithm(JWT jwt,String secretKey){
        JWTSigner signer = JWTSignerUtil.hs256(secretKey.getBytes());
        if (!jwt.verify(signer)) {
            throw new ValidatorException(Errno.LOGIN, "Signature verification failed!");
        }
    }
    /**
     * 需要捕捉ValidateException
     */
    public static void verifyDate(JWTPayload payload){
        Date expiresAt = payload.getClaimsJson().getDate("exp");
        Date now = new Date();
        if(now.after(expiresAt)){
            throw new ValidatorException(Errno.LOGIN, "token timeout");
        }
    }
    public static JWT parseToken(String token){
        return JWTUtil.parseToken(token);
    }
    /**
     * 需要捕捉ValidateException
     */
    public static long parseTokenGetUserId(JWT jwt, String userIdKey){
        verifyDate(jwt.getPayload());
        Object userId = jwt.getPayload(userIdKey);
        if(userId == null){
            throw new ValidatorException(
                    Errno.LOGIN,
                    "parseTokenGetUserId err userId[%s] not exists".formatted(userIdKey));
        }
        if(userId instanceof Long){
            return (Long) userId;
        }
        return Long.parseLong((String)userId);
    }
}
